/*
 *  MarchovicConcreteNoteGenerator.cpp
 *  SoundController0002
 *
 *  Created by jiro on 11/10/10.
 *  Copyright 2011 jiro music. All rights reserved.
 *
 */

#include "MarchovicConcreteNoteGenerator.h"
#include "ConcreteNote.h"
#include "StochasticConcreteNote.h"
#include "NullConcreteNote.h"
#include "../../sc/Utility.h"


namespace sc
{
namespace system0039
{
	MarchovicConcreteNoteGenerator::MarchovicConcreteNoteGenerator( double density, double duration )
		: ConcreteNoteGenerator( density, duration ),
		  noteMap(),
		  currentNote( NullConcreteNote() )
	{}

	void MarchovicConcreteNoteGenerator::AddChain( 
		const ConcreteNote& sourceNote, const StochasticConcreteNote& destinationNote )
	{
		AddNote( sourceNote );
		noteMap[ sourceNote ] = destinationNote;
	}

	ConcreteNote MarchovicConcreteNoteGenerator::GetConcreteNote() const
	{
		if ( currentNote.IsNull() )
		{
			currentNote = ConcreteNoteGenerator::GetConcreteNote();
			return currentNote;
		}

		std::map< ConcreteNote, StochasticConcreteNote >::const_iterator iter = noteMap.find( currentNote );
		if ( iter != noteMap.end() )
		{
			double randomValue = ::sc::RandomValueGenerator::GetValue( 0.0, 1.0 );
			if ( randomValue < GetDensity() )	//	mute note or not
			{
				currentNote = iter->second.GetConcreteNote();
				return currentNote;
			}
			else
			{
				//	don't update currentNote
				ConcreteNote note = GetMuteConcreteNote();
				return note;
			}
		}
		else
		{
			currentNote = ConcreteNoteGenerator::GetConcreteNote();
			return currentNote;
		}
	}

	std::string MarchovicConcreteNoteGenerator::ToString( int tabCount ) const
	{
		std::stringstream ss;
		std::string tabs;
		for ( int i = 0; i < tabCount; i++ )
		{
			tabs.append( "\t" );
		}
		ss << tabs << "MarchovicConcreteNoteGenerator:\n";

		std::map< ConcreteNote, StochasticConcreteNote >::const_iterator iter = noteMap.begin();
		for ( ; iter != noteMap.end(); iter++ )
		{
			ss << tabs << "map:\n" 
			   << iter->first.ToString( tabCount + 1 ) << "\n"
			   << tabs << "to\n"
			   << iter->second.ToString( tabCount + 1 ) << "\n";
		}
		ss << tabs << "currentNote:\n" << currentNote.ToString( tabCount + 1 );
		return ss.str();
	}

}
}
